home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-12-19 | 52.0 KB | 2,399 lines |
- Newsgroups: comp.sources.unix
- From: jnweiger@immd4.informatik.uni-erlangen.de (Juergen Weigert)
- Subject: v25i045: Screen3 - multiple windows on an ASCII terminal, Part05/08
- Sender: sources-moderator@pa.dec.com
- Approved: vixie@pa.dec.com
-
- Submitted-By: jnweiger@immd4.informatik.uni-erlangen.de (Juergen Weigert)
- Posting-Number: Volume 25, Issue 45
- Archive-Name: screen3/part05
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 5 (of 8)."
- # Contents: fileio.c
- # Wrapped by vixie@cognition.pa.dec.com on Thu Dec 19 17:36:05 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'fileio.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'fileio.c'\"
- else
- echo shar: Extracting \"'fileio.c'\" \(49381 characters\)
- sed "s/^X//" >'fileio.c' <<'END_OF_FILE'
- X/* Copyright (c) 1991
- X * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
- X * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
- X * Copyright (c) 1987 Oliver Laumann
- X *
- X * This program is free software; you can redistribute it and/or modify
- X * it under the terms of the GNU General Public License as published by
- X * the Free Software Foundation; either version 1, or (at your option)
- X * any later version.
- X *
- X * This program is distributed in the hope that it will be useful,
- X * but WITHOUT ANY WARRANTY; without even the implied warranty of
- X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X * GNU General Public License for more details.
- X *
- X * You should have received a copy of the GNU General Public License
- X * along with this program (see the file COPYING); if not, write to the
- X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X *
- X * Noteworthy contributors to screen's design and implementation:
- X * Wayne Davison (davison@borland.com)
- X * Patrick Wolfe (pat@kai.com, kailand!pat)
- X * Bart Schaefer (schaefer@cse.ogi.edu)
- X * Nathan Glasser (nathan@brokaw.lcs.mit.edu)
- X * Larry W. Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu)
- X * Howard Chu (hyc@hanauma.jpl.nasa.gov)
- X * Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
- X * Markku Jarvinen (mta@{cc,cs,ee}.tut.fi)
- X * Marc Boucher (marc@CAM.ORG)
- X *
- X ****************************************************************
- X */
- X
- X#ifndef lint
- X static char rcs_id[] = "$Id: fileio.c,v 1.80 91/10/11 11:27:48 jnweiger Exp $ FAU";
- X#endif
- X
- X#if defined(pyr) || defined(MIPS) || defined(GOULD_NP1) || defined(B43)
- extern int errno;
- X#endif
- X#include <sys/types.h>
- X#include <sys/file.h>
- X#include <sys/stat.h>
- X#if defined(BSD) || defined(sequent) || defined(pyr)
- X# include <strings.h>
- X#else
- X# include <string.h>
- X#endif
- X#include <fcntl.h>
- X
- X#include "config.h"
- X#include "screen.h"
- X#include "extern.h"
- X
- X#ifdef _SEQUENT_
- X# define UTHOST /* _SEQUENT_ has got ut_find_host() */
- X#endif
- X
- X#ifdef UTMPOK
- X# include <utmp.h>
- X#endif
- X
- X#ifndef GETUTENT
- X# ifdef GETTTYENT
- X# include <ttyent.h>
- X# else
- struct ttyent
- X{
- X char *ty_name;
- X};
- static char *tt, *ttnext;
- static char ttys[] = "/etc/ttys";
- X# endif
- X#endif
- X
- X#ifdef LOADAV
- X
- X#include <nlist.h>
- X
- static char KmemName[] = "/dev/kmem";
- X# if defined(_SEQUENT_) || defined(MIPS) || defined(SVR4)
- static char UnixName[] = "/unix";
- X# else
- X# ifdef sequent
- static char UnixName[] = "/dynix";
- X# else
- X# ifdef hpux
- static char UnixName[] = "/hp-ux";
- X# else
- X# ifdef xelos
- static char UnixName[] = "/xelos";
- X# else
- static char UnixName[] = "/vmunix";
- X# endif
- X# endif
- X# endif
- X# endif
- X
- X# ifdef alliant
- static char AvenrunSym[] = "_Loadavg";
- X# else
- X# if defined(hpux) || defined(_SEQUENT_) || defined(SVR4)
- static char AvenrunSym[] = "avenrun";
- X# else
- static char AvenrunSym[] = "_avenrun";
- X# endif
- X# endif
- static struct nlist nl[2];
- int avenrun;
- static kmemf;
- X# ifdef LOADAV_3LONGS
- long loadav[3];
- X# else
- X# ifdef LOADAV_4LONGS
- long loadav[4];
- X# else
- double loadav[3];
- X# endif
- X# endif
- X
- X#endif /* LOADAV */
- X
- X#define BUFFERFILE "screen-exchange"
- X
- X
- X#if defined(UTMPOK) && defined(GETUTENT)
- extern struct utmp *getutline(), *pututline();
- X# if defined(_SEQUENT_)
- extern struct utmp *ut_add_user(), *ut_delete_user();
- extern char *ut_find_host();
- X# endif
- X#endif
- X#ifdef NETHACK
- extern nethackflag;
- X#endif
- X
- extern char *RcFileName, *home, *extra_incap, *extra_outcap;
- extern char *BellString, *ActivityString, *ShellProg, *ShellArgs[];
- extern char *PowDetachString, *VisualBellString;
- extern int VBellWait, MsgWait, MsgMinWait;
- extern struct key ktab[];
- extern char Esc, MetaEsc;
- extern char *shellaka, SockPath[], *SockNamePtr, *LoginName;
- extern loginflag, TtyMode, auto_detach;
- extern iflag, mflag, rflag, dflag;
- extern flowctl, wrap;
- extern HS, termcapHS, use_hardstatus, visual_bell, default_monitor;
- extern default_histheight;
- extern default_startup;
- extern slowpaste;
- extern DeadlyMsg, HasWindow;
- extern ForeNum, screenwidth, screenheight;
- extern struct win *fore;
- extern char screenterm[];
- extern int join_with_cr;
- extern struct mode OldMode, NewMode;
- extern int HasWindow;
- extern char mark_key_tab[];
- extern int real_uid, eff_uid;
- extern int real_gid, eff_gid;
- X
- X#ifdef PASSWORD
- int CheckPassword;
- char Password[20];
- X#endif
- X
- X#ifdef COPY_PASTE
- extern char *copybuffer;
- extern copylen;
- X#endif
- X
- static char *CatExtra __P((char *, char *));
- static char **SaveArgs __P((int, char **));
- static int Parse __P((char *, char **));
- static int IsNum __P((char *, int));
- static int IsNumColon __P((char *, int, char *));
- static char *stripdev __P((char *));
- static slot_t TtyNameSlot __P((char *));
- X
- X#if !defined(GETTTYENT) && !defined(GETUTENT)
- static void setttyent __P((void));
- static struct ttyent *getttyent __P((void));
- X#endif
- X
- X/*
- X * XXX: system
- X */
- extern time_t time __P((time_t *));
- X#ifndef SVR4
- extern char *getpass __P((char *));
- X# ifdef LOADAV
- extern int nlist __P((char *, struct nlist *));
- X# endif
- X#endif
- X
- char *KeyNames[] =
- X{
- X "screen",
- X "select0", "select1", "select2", "select3", "select4",
- X "select5", "select6", "select7", "select8", "select9",
- X "aka", "autoflow", "clear", "colon", "copy", "detach", "flow",
- X "hardcopy", "help", "history", "info", "kill", "lastmsg", "license",
- X "lockscreen", "log", "login", "monitor", "next", "other", "paste",
- X "pow_detach", "prev", "quit", "readbuf", "redisplay", "removebuf",
- X "reset", "set", "shell", "suspend", "termcap", "time", "vbell",
- X "version", "width", "windows", "wrap", "writebuf", "xoff", "xon",
- X 0,
- X};
- X
- X
- X/* Must be in alpha order !!! */
- X
- char *RCNames[] =
- X{
- X "activity", "all", "autodetach", "bell", "bind", "chdir", "crlf",
- X "echo", "escape", "flow", "hardstatus", "login", "markkeys", "mode",
- X "monitor", "msgminwait", "msgwait", "nethack", "password",
- X "pow_detach_msg", "screen", "scrollback", "shell", "shellaka",
- X "sleep", "slowpaste", "startup_message", "term", "termcap",
- X "terminfo", "vbell", "vbell_msg", "vbellwait", "visualbell",
- X "visualbell_msg", "wrap",
- X};
- X
- enum RCcases
- X{
- X RC_ACTIVITY,
- X RC_ALL,
- X RC_AUTODETACH,
- X RC_BELL,
- X RC_BIND,
- X RC_CHDIR,
- X RC_CRLF,
- X RC_ECHO,
- X RC_ESCAPE,
- X RC_FLOW,
- X RC_HARDSTATUS,
- X RC_LOGIN,
- X RC_MARKKEYS,
- X RC_MODE,
- X RC_MONITOR,
- X RC_MSGMINWAIT,
- X RC_MSGWAIT,
- X RC_NETHACK,
- X RC_PASSWORD,
- X RC_POW_DETACH_MSG,
- X RC_SCREEN,
- X RC_SCROLLBACK,
- X RC_SHELL,
- X RC_SHELLAKA,
- X RC_SLEEP,
- X RC_SLOWPASTE,
- X RC_STARTUP_MESSAGE,
- X RC_TERM,
- X RC_TERMCAP,
- X RC_TERMINFO,
- X RC_VBELL,
- X RC_VBELL_MSG,
- X RC_VBELLWAIT,
- X RC_VISUALBELL,
- X RC_VISUALBELL_MSG,
- X RC_WRAP,
- X RC_RCEND,
- X};
- X
- X
- X#ifdef UTMPOK
- static utmp, utmpf;
- static char UtmpName[] = "/etc/utmp";
- X# ifdef MIPS
- X static utmpfappend;
- X# endif
- X#endif
- X
- static FILE *fp = NULL;
- static char *rc_name;
- X
- char *SaveStr(str)
- register char *str;
- X{
- X register char *cp;
- X
- X if ((cp = malloc((unsigned) strlen(str) + 1)) == NULL)
- X Msg_nomem;
- X else
- X strcpy(cp, str);
- X return cp;
- X}
- X
- static char *CatExtra(str1, str2)
- register char *str1, *str2;
- X{
- X register char *cp;
- X register int len1, len2, add_colon;
- X
- X len1 = strlen(str1);
- X if (len1 == 0)
- X return(str2);
- X add_colon = (str1[len1 - 1] != ':');
- X if (str2)
- X {
- X len2 = strlen(str2);
- X if ((cp = realloc(str2, (unsigned) len1 + len2 + add_colon + 1)) == NULL)
- X Msg_nomem;
- X bcopy(cp, cp + len1 + add_colon, len2 + 1);
- X }
- X else
- X {
- X if (len1 == 0)
- X return 0;
- X if ((cp = malloc((unsigned) len1 + add_colon + 1)) == NULL)
- X Msg_nomem;
- X }
- X bcopy(str1, cp, len1);
- X if (add_colon)
- X cp[len1] = ':';
- X
- X return cp;
- X}
- X
- static char *findrcfile(rcfile)
- char *rcfile;
- X{
- X static char buf[256];
- X char *rc, *p;
- X
- X if (rcfile)
- X {
- X rc = SaveStr(rcfile);
- X debug1("findrcfile: you specified '%s'\n", rcfile);
- X }
- X else
- X {
- X debug("findrcfile: you specified nothing...\n");
- X if ((p = getenv("ISCREENRC")) != NULL && *p != '\0')
- X {
- X debug1(" ... but $ISCREENRC has: '%s'\n", p);
- X rc = SaveStr(p);
- X }
- X else if ((p = getenv("SCREENRC")) != NULL && *p != '\0')
- X {
- X debug1(" ... but $SCREENRC has: '%s'\n", p);
- X rc = SaveStr(p);
- X }
- X else
- X {
- X debug(" ...nothing in $SCREENRC, defaulting $HOME/.screenrc\n");
- X if ((unsigned)strlen(home) > 244)
- X Msg(0, "Rc: home too large");
- X sprintf(buf, "%s/.iscreenrc", home);
- X if (access(buf, R_OK))
- X sprintf(buf, "%s/.screenrc", home);
- X rc = SaveStr(buf);
- X }
- X }
- X return rc;
- X}
- X
- X/*
- X * this will be called twice:
- X * 1) rcfilename = "/etc/screenrc"
- X * 2) rcfilename = RcFileName
- X */
- void
- StartRc(rcfilename)
- char *rcfilename;
- X{
- X register int argc, len;
- X register char *p, *cp;
- X char buf[256];
- X char *args[MAXARGS], *t;
- X
- X rc_name = findrcfile(rcfilename);
- X
- X if ((fp = secfopen(rc_name, "r")) == NULL)
- X {
- X if (RcFileName && strcmp(RcFileName, rc_name) == 0)
- X {
- X /*
- X * User explicitly gave us that name,
- X * this is the only case, where we get angry, if we can't read
- X * the file.
- X */
- X debug3("StartRc: '%s','%s', '%s'\n", RcFileName, rc_name, rcfilename);
- X Msg(0, "Unable to open \"%s\".", rc_name);
- X /* NOTREACHED */
- X }
- X debug1("StartRc: '%s' no good. ignored\n", rc_name);
- X Free(rc_name);
- X rc_name = "";
- X return;
- X }
- X if ((t = getenv("TERM")) == NULL)
- X Msg(0, "No TERM in environment.");
- X debug1("startrc got termcp:%s\n", t);
- X while (fgets(buf, sizeof buf, fp) != NULL)
- X {
- X if ((p = rindex(buf, '\n')) != NULL)
- X *p = '\0';
- X if ((argc = Parse(buf, args)) == 0)
- X continue;
- X if (strcmp(args[0], "echo") == 0)
- X {
- X if (argc < 2 || (argc == 3 && strcmp(args[1], "-n")) || argc > 3)
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: 'echo [-n] \"string\"' expected.", rc_name);
- X }
- X else
- X {
- X printf((argc == 3) ? "%s" : "%s\r\n", args[argc - 1]);
- X }
- X }
- X else if (strcmp(args[0], "sleep") == 0)
- X {
- X if (argc != 2)
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: sleep: one numeric argument expected.", rc_name);
- X }
- X else
- X sleep(atoi(args[1]));
- X }
- X#ifdef TERMINFO
- X else if (strcmp(args[0], "terminfo") == 0)
- X#else
- X else if (strcmp(args[0], "termcap") == 0)
- X#endif
- X {
- X if (argc < 3 || argc > 4)
- X Msg(0, "%s: %s: incorrect number of arguments.", rc_name, args[0]);
- X for (p = args[1]; p && *p; p = cp)
- X {
- X if ((cp = index(p, '|')) != 0)
- X *cp++ = '\0';
- X len = strlen(p);
- X if (p[len - 1] == '*')
- X {
- X if (!(len - 1) || !strncmp(p, t, len - 1))
- X break;
- X }
- X else if (!strcmp(p, t))
- X break;
- X }
- X if (!(p && *p))
- X continue;
- X extra_incap = CatExtra(args[2], extra_incap);
- X if (argc == 4)
- X extra_outcap = CatExtra(args[3], extra_outcap);
- X }
- X }
- X fclose(fp);
- X Free(rc_name);
- X rc_name = "";
- X}
- X
- char *ParseChar(p, cp)
- char *p, *cp;
- X{
- X if (*p == '^')
- X {
- X if (*++p == '?')
- X *cp = '\177';
- X else if (*p >= '@')
- X *cp = Ctrl(*p);
- X else
- X return 0;
- X ++p;
- X }
- X else if (*p == '\\' && *++p <= '7' && *p >= '0')
- X {
- X *cp = 0;
- X do
- X *cp = *cp * 8 + *p - '0';
- X while (*++p <= '7' && *p >= '0');
- X }
- X else
- X *cp = *p++;
- X return p;
- X}
- X
- X/*
- X * CompileKeys must be called before Markroutine is first used.
- X * to initialise the keys with defaults, call CompileKeys(NULL, mark_key_tab);
- X *
- X * s is an ascii string in a termcap-like syntax. It looks like
- X * "j=u:k=d:l=r:h=l: =.:" and so on...
- X * this example rebinds the cursormovement to the keys u (up), d (down),
- X * l (left), r (right). placing a mark will now be done with ".".
- X */
- int CompileKeys(s, array)
- char *s, *array;
- X{
- X int i;
- X unsigned char key, value;
- X
- X if (!s || !*s)
- X {
- X for (i = 0; i < 256; i++)
- X array[i] = i;
- X return 0;
- X }
- X while (*s)
- X {
- X s = ParseChar(s, (char *) &key);
- X if (*s != '=')
- X return -1;
- X do
- X {
- X s = ParseChar(++s, (char *) &value);
- X array[value] = key;
- X }
- X while (*s == '=');
- X if (!*s)
- X break;
- X if (*s++ != ':')
- X return -1;
- X }
- X return 0;
- X}
- X
- static char **SaveArgs(argc, argv)
- register int argc;
- register char **argv;
- X{
- X register char **ap, **pp;
- X
- X if ((pp = ap = (char **) malloc((unsigned) (argc + 1) * sizeof(char **))) == 0)
- X Msg_nomem;
- X#ifdef notdef
- X debug("saveargs:\n");
- X#endif
- X while (argc--)
- X {
- X debug1(" '%s'", *argv);
- X *pp++ = SaveStr(*argv++);
- X }
- X debug("\n");
- X *pp = 0;
- X return ap;
- X}
- X
- void
- AbortRc()
- X{
- X debug("AbortRc();\n");
- X if (fp == NULL)
- X debug(" fp not open\n")
- X else
- X (void) fclose(fp);
- X}
- X
- void
- XFinishRc(rcfilename)
- char *rcfilename;
- X{
- X /* in FinishRc screen is not yet open, thus Msg() is deadly here.
- X */
- X char buf[256];
- X
- X rc_name = findrcfile(rcfilename);
- X
- X if ((fp = secfopen(rc_name, "r")) == NULL)
- X {
- X if (RcFileName && strcmp(RcFileName, rc_name) == 0)
- X {
- X /*
- X * User explicitly gave us that name,
- X * this is the only case, where we get angry, if we can't read
- X * the file.
- X */
- X debug3("FinishRc:'%s','%s','%s'\n", RcFileName, rc_name, rcfilename);
- X Msg(0, "Unable to open \"%s\".", rc_name);
- X /* NOTREACHED */
- X }
- X debug1("FinishRc: '%s' no good. ignored\n", rc_name);
- X Free(rc_name);
- X rc_name = "";
- X return;
- X }
- X
- X debug("finishrc is going...\n");
- X while (fgets(buf, sizeof buf, fp) != NULL)
- X {
- X RcLine(buf);
- X }
- X (void) fclose(fp);
- X Free(rc_name);
- X rc_name = "";
- X}
- X
- X/*
- X * this is a KEY_SET pressed
- X */
- void
- DoSet(argv)
- char **argv;
- X{
- X char *p;
- X static char buf[256];
- X
- X p = buf;
- X debug("DoSet\n");
- X if (!argv || !*argv || !**argv)
- X {
- X debug("empty DoSet\n");
- X sprintf(buf, "set ");
- X RcLine(buf);
- X return;
- X }
- X sprintf(p, "set"); p+=3;
- X while(*argv && ((unsigned)strlen(buf) + (unsigned)strlen(*argv) < 255))
- X {
- X sprintf(p, " %s", *argv++);
- X p += strlen(p);
- X }
- X RcLine(buf);
- X}
- X
- X/*
- X * "$HOST blafoo" -> "localhost blafoo"
- X * "${HOST}blafoo" -> "localhostblafoo"
- X * "\$HOST blafoo" -> "$HOST blafoo"
- X * "\\$HOST blafoo" -> "\localhost blafoo"
- X * "'$HOST ${HOST}'" -> "'$HOST ${HOST}'"
- X * "'\$HOST'" -> "'\$HOST'"
- X * "\'$HOST' $HOST" -> "'localhost' $HOST"
- X */
- static char *expand_env_vars(ss)
- char *ss;
- X{
- X static char ebuf[2048];
- X register int esize = 2047, quofl = 0;
- X register char *e = ebuf;
- X register char *s = ss;
- X register char *v;
- X
- X while (*s && *s != '\n' && esize > 0)
- X {
- X if (*s == '\'')
- X quofl ^= 1;
- X if (*s == '$' && !quofl)
- X {
- X char *p, c;
- X
- X p = ++s;
- X if (*s == '{')
- X {
- X p = ++s;
- X while (*p != '}')
- X if (*p++ == '\0')
- X return ss;
- X }
- X else
- X {
- X while (*p != ' ' && *p != '\0' && *p != '\n')
- X p++;
- X }
- X c = *p;
- X debug1("exp: c='%c'\n", c);
- X *p = '\0';
- X if (v = getenv(s))
- X {
- X debug2("exp: $'%s'='%s'\n", s, v);
- X while (*v && esize-- > 0)
- X *e++ = *v++;
- X }
- X else
- X debug1("exp: '%s' not env\n", s);
- X if ((*p = c) == '}')
- X p++;
- X s = p;
- X }
- X else
- X {
- X if (s[0] == '\\' && !quofl)
- X if (s[1] == '$' || (s[1] == '\\' && s[2] == '$') ||
- X s[1] == '\'' || (s[1] == '\\' && s[2] == '\''))
- X s++;
- X *e++ = *s++;
- X esize--;
- X }
- X }
- X if (esize <= 0)
- X Msg(0, "expand_env_vars: buffer overflow\n");
- X *e = '\0';
- X return ebuf;
- X}
- X
- void
- RcLine(ubuf)
- char *ubuf;
- X{
- X char *args[MAXARGS];
- X register char *buf, *p, **pp, **ap;
- X register int argc, setflag;
- X int q, qq;
- X char key;
- X int low, high, mid, x;
- X
- X buf = expand_env_vars(ubuf);
- X
- X ap = args;
- X
- X if ((p = rindex(buf, '\n')) != NULL)
- X *p = '\0';
- X if (strncmp("set ", buf, 4) == 0)
- X {
- X buf += 4;
- X setflag = 1;
- X debug1("RcLine: '%s' is a set command\n", buf);
- X }
- X else if (strncmp("se ", buf, 3) == 0)
- X {
- X buf += 3;
- X setflag = 1;
- X debug1("RcLine: '%s' is a se command\n", buf);
- X }
- X else
- X {
- X setflag = 0;
- X debug1("RcLine: '%s'\n", buf);
- X }
- X if ((argc = Parse(buf, ap)) == 0)
- X {
- X if (setflag)
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: set what?\n", rc_name);
- X }
- X return;
- X }
- X
- X low = 0;
- X high = (int)RC_RCEND - 1;
- X while (low <= high)
- X {
- X mid = (low + high) / 2;
- X x = strcmp(ap[0], RCNames[mid]);
- X if (x < 0)
- X high = mid - 1;
- X else if (x > 0)
- X low = mid + 1;
- X else
- X break;
- X }
- X if (low > high)
- X mid = (int)RC_RCEND;
- X switch ((enum RCcases) mid)
- X {
- X case RC_ESCAPE:
- X if (argc != 2 || !ParseEscape(ap[1]))
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: two characters required after escape.", rc_name);
- X return;
- X }
- X if (Esc != MetaEsc)
- X ktab[Esc].type = KEY_OTHER;
- X else
- X ktab[Esc].type = KEY_IGNORE;
- X return;
- X case RC_CHDIR:
- X if (setflag)
- X break;
- X p = argc < 2 ? home : ap[1];
- X if (chdir(p) == -1)
- X {
- X DeadlyMsg = 0;
- X Msg(errno, "%s", p);
- X }
- X return;
- X case RC_SHELL:
- X if (argc != 2)
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: shell: one argument required.", rc_name);
- X return;
- X }
- X ShellProg = ShellArgs[0] = SaveStr(ap[1]);
- X return;
- X case RC_SHELLAKA:
- X if (argc != 2)
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: shellaka: one argument required.", rc_name);
- X return;
- X }
- X shellaka = SaveStr(ap[1]);
- X return;
- X case RC_SCREEN:
- X if (setflag)
- X break;
- X DoScreen(rc_name, ap + 1);
- X return;
- X case RC_SLEEP:
- X case RC_TERMCAP:
- X case RC_TERMINFO:
- X return; /* Already handled */
- X case RC_TERM:
- X if ((argc != 2) || ((unsigned)strlen(args[1]) >= 20))
- X {
- X DeadlyMsg = 0;
- X Msg(0,"%s: term: one argument required.", rc_name);
- X return;
- X }
- X strcpy(screenterm, args[1]);
- X debug1("screenterm set to %s\n", screenterm);
- X MakeTermcap(0);
- X return;
- X case RC_ECHO:
- X if (HasWindow && *rc_name == '\0')
- X {
- X /*
- X * user typed ^A:echo... well, echo isn't FinishRc's job,
- X * but as he wanted to test us, we show good will
- X */
- X DeadlyMsg = 0;
- X if (argc == 2 || (argc == 3 && !strcmp(ap[1], "-n")))
- X Msg(0, "%s", ap[argc - 1]);
- X else
- X Msg(0, "%s: 'echo [-n] \"string\"' expected.", rc_name);
- X }
- X return;
- X case RC_BELL:
- X if (argc != 2)
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: bell: one argument required.", rc_name);
- X return;
- X }
- X if (BellString)
- X Free(BellString);
- X BellString = SaveStr(ap[1]);
- X return;
- X case RC_ACTIVITY:
- X if (argc != 2)
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: activity: one argument required.", rc_name);
- X return;
- X }
- X if (ActivityString)
- X Free(ActivityString);
- X ActivityString = SaveStr(ap[1]);
- X return;
- X case RC_POW_DETACH_MSG:
- X if (argc != 2)
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: pow_detach: one argument required.", rc_name);
- X return;
- X }
- X if (PowDetachString)
- X Free(PowDetachString);
- X PowDetachString = SaveStr(ap[1]);
- X return;
- X case RC_LOGIN:
- X#ifdef UTMPOK
- X q = loginflag;
- X ParseOnOff(argc, ap, &loginflag);
- X if (fore && setflag)
- X {
- X SlotToggle(loginflag?(1):(-1));
- X loginflag = q;
- X }
- X#endif
- X return;
- X case RC_FLOW:
- X if (argc == 3 && ap[2][0] == 'i')
- X {
- X iflag = 1;
- X argc--;
- X }
- X if (argc == 2 && ap[1][0] == 'a')
- X flowctl = 3;
- X else
- X {
- X ParseOnOff(argc, ap, &flowctl);
- X flowctl++;
- X }
- X return;
- X case RC_WRAP:
- X ParseOnOff(argc, ap, &wrap);
- X return;
- X case RC_HARDSTATUS:
- X ParseOnOff(argc, ap, &use_hardstatus);
- X if (use_hardstatus)
- X HS = termcapHS;
- X else
- X HS = 0;
- X return;
- X case RC_MONITOR:
- X {
- X int f;
- X
- X ParseOnOff(argc, ap, &f);
- X if (fore && setflag)
- X fore->monitor = (f == 0) ? MON_OFF : MON_ON;
- X else
- X default_monitor = (f == 0) ? MON_OFF : MON_ON;
- X }
- X return;
- X case RC_VBELL:
- X case RC_VISUALBELL:
- X ParseOnOff(argc, ap, &visual_bell);
- X return;
- X case RC_VBELLWAIT:
- X ParseNum(argc, ap, &VBellWait);
- X if (fore && rc_name[0] == '\0')
- X Msg(0, "vbellwait set to %d seconds", VBellWait);
- X return;
- X case RC_MSGWAIT:
- X ParseNum(argc, ap, &MsgWait);
- X if (fore && rc_name[0] == '\0')
- X Msg(0, "msgwait set to %d seconds", MsgWait);
- X return;
- X case RC_MSGMINWAIT:
- X ParseNum(argc, ap, &MsgMinWait);
- X if (fore && rc_name[0] == '\0')
- X Msg(0, "msgminwait set to %d seconds", MsgMinWait);
- X return;
- X case RC_SCROLLBACK:
- X if (fore && setflag)
- X {
- X int i;
- X
- X ParseNum(argc, ap, &i);
- X ChangeScrollback(fore, i, fore->width);
- X if (fore && rc_name[0] == '\0')
- X Msg(0, "scrollback set to %d", fore->histheight);
- X }
- X else
- X ParseNum(argc, ap, &default_histheight);
- X return;
- X case RC_SLOWPASTE:
- X ParseNum(argc, ap, &slowpaste);
- X if (fore && rc_name[0] == '\0')
- X Msg(0, "slowpaste set to %d milliseconds", slowpaste);
- X return;
- X case RC_MARKKEYS:
- X if (argc != 2)
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: markkeys: one argument required.", rc_name);
- X return;
- X }
- X if (CompileKeys(ap[1], mark_key_tab))
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: markkeys: syntax error.", rc_name);
- X return;
- X }
- X debug1("markkeys %s\n", ap[1]);
- X return;
- X#ifdef NETHACK
- X case RC_NETHACK:
- X ParseOnOff(argc, ap, &nethackflag);
- X return;
- X#endif
- X case RC_VBELL_MSG:
- X case RC_VISUALBELL_MSG:
- X if (argc != 2)
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: vbell_msg: one argument required.", rc_name);
- X return;
- X }
- X if (VisualBellString)
- X Free(VisualBellString);
- X VisualBellString = SaveStr(ap[1]);
- X debug1(" new vbellstr '%s'\n", VisualBellString);
- X return;
- X case RC_MODE:
- X if (argc != 2)
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: mode: one argument required.", rc_name);
- X return;
- X }
- X if (!IsNum(ap[1], 7))
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: mode: octal number expected.", rc_name);
- X return;
- X }
- X (void) sscanf(ap[1], "%o", &TtyMode);
- X return;
- X case RC_CRLF:
- X ParseOnOff(argc, ap, &join_with_cr);
- X return;
- X case RC_AUTODETACH:
- X ParseOnOff(argc, ap, &auto_detach);
- X return;
- X case RC_STARTUP_MESSAGE:
- X ParseOnOff(argc, ap, &default_startup);
- X return;
- X#ifdef PASSWORD
- X case RC_PASSWORD:
- X CheckPassword = 1;
- X if (argc >= 2)
- X {
- X strncpy(Password, ap[1], sizeof Password);
- X if (!strcmp(Password, "none"))
- X CheckPassword = 0;
- X }
- X else
- X {
- X char *mstr = 0;
- X int msleep = 0, st;
- X char salt[2];
- X
- X /* there is a clear screen sequence in the buffer. */
- X fflush(stdout);
- X if (HasWindow)
- X {
- X ClearDisplay();
- X SetTTY(0, &OldMode);
- X }
- X strncpy(Password, getpass("New screen password:"),
- X sizeof(Password));
- X if (strcmp(Password, getpass("Retype new password:")))
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X mstr = "[ Passwords don't match - your armor crumbles away ]";
- X else
- X#endif
- X mstr = "[ Passwords don't match - checking turned off ]";
- X msleep = 1;
- X CheckPassword = 0;
- X }
- X if (Password[0] == '\0')
- X {
- X CheckPassword = 0;
- X mstr = "[ No password - no secure ]";
- X msleep = 1;
- X }
- X for (st=0; st<2; st++)
- X salt[st] = 'A' + (int)((time(0) >> 6*st) % 26);
- X strncpy(Password, crypt(Password, salt), sizeof(Password));
- X if (CheckPassword)
- X {
- X#ifdef COPY_PASTE
- X if (copybuffer)
- X
- X Free(copybuffer);
- X copylen = strlen(Password);
- X if ((copybuffer = (char *) malloc(copylen+1)) == NULL)
- X {
- X Msg_nomem;
- X return;
- X }
- X strcpy(copybuffer, Password);
- X mstr = "[ Password moved into copybuffer ]";
- X msleep = 1;
- X#else /* COPY_PASTE */
- X mstr = "[ Crypted password is \"%s\" ]";
- X msleep = 4;
- X#endif /* COPY_PASTE */
- X }
- X if (HasWindow)
- X {
- X SetTTY(0, &NewMode);
- X Activate(); /* Redraw */
- X if (mstr)
- X {
- X Msg(0, mstr, Password);
- X }
- X }
- X else
- X {
- X if (mstr)
- X {
- X printf(mstr, Password);
- X putchar('\n');
- X sleep(msleep);
- X }
- X ClearDisplay();
- X }
- X }
- X debug1("finishrc: our password is: --%s%-- \n", Password);
- X return;
- X#endif /* PASSWORD */
- X case RC_ALL:
- X if (!setflag || !HasWindow || *rc_name)
- X break;
- X display_help();
- X return;
- X case RC_BIND:
- X if (setflag)
- X break;
- X p = ap[1];
- X if (argc < 2 || *p == '\0')
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: key expected after bind.", rc_name);
- X return;
- X }
- X if ((p = ParseChar(p, &key)) == NULL || *p)
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: bind: character, ^x, or (octal) \\032 expected.",
- X rc_name);
- X return;
- X }
- X if (ktab[key].type != KEY_IGNORE)
- X {
- X ktab[key].type = KEY_IGNORE;
- X if ((pp = ktab[key].args) != NULL)
- X {
- X for (; *pp; pp++)
- X Free(*pp);
- X Free(ktab[key].args);
- X }
- X }
- X if (argc > 2)
- X {
- X for (pp = KeyNames; *pp; ++pp)
- X if (strcmp(ap[2], *pp) == 0)
- X break;
- X if (*pp)
- X {
- X ktab[key].type = (enum keytype) (pp - KeyNames + 1);
- X if (argc > 3)
- X {
- X ktab[key].args = SaveArgs(argc - 3, ap + 3);
- X }
- X else
- X ktab[key].args = NULL;
- X }
- X else
- X {
- X ktab[key].type = KEY_CREATE;
- X ktab[key].args = SaveArgs(argc - 2, ap + 2);
- X }
- X }
- X return;
- X case RC_RCEND:
- X default:
- X {
- X char ibuf[3];
- X /*
- X * now we are user-friendly:
- X * if anyone typed a key name like "help" or "next" ...
- X * we did not match anything above. so look in the KeyNames table.
- X */
- X debug1("--ap[0] %s\n", ap[0]);
- X for (pp = KeyNames; *pp; ++pp)
- X if (strcmp(ap[0], *pp) == 0)
- X break;
- X if (*pp == 0)
- X break;
- X
- X ibuf[0] = Esc;
- X ibuf[1] = pp - KeyNames +1;
- X debug1("RcLine: it was a keyname: '%s'\n", *pp);
- X q = 2; qq = 0;
- X if (HasWindow)
- X ProcessInput(ibuf, &q, (char *)0, &qq, 0);
- X else
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: Key '%s' has no effect while no window open...\n",
- X rc_name, ap[0]);
- X }
- X }
- X return;
- X }
- X DeadlyMsg = 0;
- X Msg(0, "%s: unknown %skeyword \"%s\"", rc_name,
- X setflag?"'set' ":"", ap[0]);
- X}
- X
- static int Parse(buf, args)
- char *buf, **args;
- X{
- X register char *p = buf, **ap = args;
- X register int delim, argc;
- X
- X argc = 0;
- X for (;;)
- X {
- X while (*p && (*p == ' ' || *p == '\t'))
- X ++p;
- X if (*p == '\0' || *p == '#')
- X {
- X *p = '\0';
- X return argc;
- X }
- X if (argc > MAXARGS - 1)
- X Msg(0, "%s: too many tokens.", rc_name);
- X delim = 0;
- X if (*p == '"' || *p == '\'')
- X delim = *p++;
- X argc++;
- X *ap = p;
- X *++ap = 0;
- X while (*p && !(delim ? *p == delim : (*p == ' ' || *p == '\t')))
- X ++p;
- X if (*p == '\0')
- X {
- X if (delim)
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: Missing quote.", rc_name);
- X return 0;
- X }
- X return argc;
- X }
- X *p++ = '\0';
- X }
- X}
- X
- int ParseEscape(p)
- char *p;
- X{
- X if ((p = ParseChar(p, &Esc)) == NULL ||
- X (p = ParseChar(p, &MetaEsc)) == NULL || *p)
- X return 0;
- X return 1;
- X}
- X
- void
- ParseNum(argc, ap, var)
- int argc;
- char *ap[];
- int *var;
- X{
- X int i;
- X char *p;
- X
- X if (argc == 2 && ap[1][0] != '\0')
- X {
- X i = 0;
- X p = ap[1];
- X while (*p)
- X {
- X if (*p >= '0' && *p <= '9')
- X i = 10 * i + (*p - '0');
- X else
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: %s: invalid argument. Give numeric argument",
- X rc_name, ap[0]);
- X return;
- X }
- X p++;
- X }
- X }
- X else
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: %s: invalid argument. Give one argument",
- X rc_name, ap[0]);
- X return;
- X }
- X debug1("ParseNum got %d\n", i);
- X *var = i;
- X}
- X
- void
- ParseOnOff(argc, ap, var)
- int argc;
- char *ap[];
- int *var;
- X{
- X register int num = -1;
- X
- X if (argc == 2 && ap[1][0] == 'o')
- X {
- X if (ap[1][1] == 'f')
- X num = 0;
- X else if (ap[1][1] == 'n')
- X num = 1;
- X }
- X if (num < 0)
- X {
- X DeadlyMsg = 0;
- X Msg(0, "%s: %s: invalid argument. Give 'on' or 'off'", rc_name, ap[0]);
- X return;
- X }
- X *var = num;
- X}
- X
- X
- static int IsNum(s, base)
- register char *s;
- register int base;
- X{
- X for (base += '0'; *s; ++s)
- X if (*s < '0' || *s > base)
- X return 0;
- X return 1;
- X}
- X
- static int IsNumColon(s, base, p)
- int base;
- char *s, *p;
- X{
- X char *q;
- X if ((q = rindex(s, ':')) != NULL)
- X {
- X strncpy(p, q + 1, 19);
- X *q = '\0';
- X }
- X else
- X *p = '\0';
- X return IsNum(s, base);
- X}
- X
- void
- SlotToggle(how)
- int how;
- X/*
- X * how = 0 real toggle mode
- X * how > 0 do try to set a utmp slot.
- X * how < 0 try to withdraw a utmp slot
- X *
- X * slot = -1 window not logged in.
- X * slot = 0 window not logged in, but should be logged in.
- X * (unable to write utmp, or detached).
- X */
- X{
- X debug1("SlotToggle %d\n", how);
- X if (how == 0)
- X how = (fore->slot == (slot_t) -1)?(1):(-1);
- X /*
- X * slot 0 or active -> we try to log out.
- X * slot -1 -> we try to log in.
- X */
- X#ifdef UTMPOK
- X if (how > 0)
- X {
- X debug(" try to log in\n");
- X if ((fore->slot == (slot_t) -1) || (fore->slot == (slot_t) 0))
- X {
- X#ifdef USRLIMIT
- X if (CountUsers() >= USRLIMIT)
- X Msg(0, "User limit reached.");
- X else
- X#endif
- X {
- X if (SetUtmp(fore, ForeNum) == 0)
- X Msg(0, "This window is now logged in.");
- X else
- X Msg(0, "This window should now be logged in.");
- X }
- X }
- X else
- X Msg(0, "This window is already logged in.");
- X }
- X else if (how < 0)
- X {
- X debug(" try to log out\n");
- X if (fore->slot == (slot_t) -1)
- X Msg(0, "This window is already logged out\n");
- X else if (fore->slot == (slot_t) 0)
- X {
- X debug("What a relief! In fact, it was not logged in\n");
- X Msg(0, "This window is not logged in.");
- X fore->slot = (slot_t) -1;
- X }
- X else
- X {
- X RemoveUtmp(fore);
- X if (fore->slot != (slot_t) -1)
- X Msg(0, "What? Cannot remove Utmp slot?");
- X else
- X Msg(0, "This window is no longer logged in.");
- X }
- X }
- X#else /* !UTMPOK */
- X Msg(0, "Unable to modify /etc/utmp.\n");
- X#endif
- X}
- X
- void
- DoScreen(fn, av)
- char *fn, **av;
- X{
- X register int flowflag, num, lflag = loginflag;
- X register char *aka = NULL;
- X register int histheight = default_histheight;
- X char buf[20];
- X char termbuf[25];
- X char *termp;
- X char *args[2];
- X
- X flowflag = flowctl;
- X termbuf[0] = '\0';
- X termp = NULL;
- X while (av && *av && av[0][0] == '-')
- X {
- X switch (av[0][1])
- X {
- X case 'f':
- X switch (av[0][2])
- X {
- X case 'n':
- X case '0':
- X flowflag = 1;
- X break;
- X case 'y':
- X case '1':
- X case '\0':
- X flowflag = 2;
- X break;
- X case 'a':
- X flowflag = 3;
- X break;
- X default:
- X break;
- X }
- X break;
- X case 'k':
- X case 't':
- X if (av[0][2])
- X aka = &av[0][2];
- X else if (*++av)
- X aka = *av;
- X else
- X --av;
- X break;
- X case 'T':
- X if (av[0][2])
- X termp = &av[0][2];
- X else if (*++av)
- X termp = *av;
- X else
- X --av;
- X break;
- X case 'h':
- X if (av[0][2])
- X histheight = atoi(av[0] + 2);
- X else if (*++av)
- X histheight = atoi(*av);
- X else
- X --av;
- X break;
- X case 'l':
- X switch (av[0][2])
- X {
- X case 'n':
- X case '0':
- X lflag = 0;
- X break;
- X case 'y':
- X case '1':
- X case '\0':
- X lflag = 1;
- X break;
- X default:
- X break;
- X }
- X break;
- X default:
- X Msg(0, "%s: screen: invalid option -%c.", fn, av[0][1]);
- X break;
- X }
- X ++av;
- X }
- X num = 0;
- X if (av && *av && IsNumColon(*av, 10, buf))
- X {
- X if (*buf != '\0')
- X aka = buf;
- X num = atoi(*av);
- X if (num < 0 || num > MAXWIN - 1)
- X Msg(0, "%s: illegal screen number %d.", fn, num);
- X ++av;
- X }
- X if (!av || !*av)
- X {
- X av = args;
- X av[0] = ShellProg;
- X av[1] = NULL;
- X if (!aka)
- X aka = shellaka;
- X }
- X MakeWindow(aka, av, 0, flowflag, num, (char *) 0, lflag, histheight, termp);
- X}
- X
- void
- WriteFile(dump)
- int dump;
- X{
- X /* dump==0: create .termcap,
- X * dump==1: hardcopy,
- X * #ifdef COPY_PASTE
- X * dump==2: BUFFERFILE
- X * #endif COPY_PASTE
- X */
- X register int i, j, k;
- X register char *p;
- X register FILE *f;
- X char fn[1024];
- X
- X switch (dump)
- X {
- X case DUMP_TERMCAP:
- X i = SockNamePtr - SockPath;
- X strncpy(fn, SockPath, i);
- X strcpy(fn + i, ".termcap");
- X break;
- X case DUMP_HARDCOPY:
- X sprintf(fn, "hardcopy.%d", ForeNum);
- X break;
- X case DUMP_EXCHANGE:
- X sprintf(fn, "/tmp/%s", BUFFERFILE);
- X umask(0);
- X break;
- X }
- X
- X debug2("WriteFile(%d) %s\n", dump, fn);
- X if (UserContext() > 0)
- X {
- X debug("Writefile: usercontext\n");
- X if ((f = fopen(fn, "w")) == NULL)
- X {
- X debug1("WriteFile: fopen(%s) failed\n", fn);
- X UserReturn(0);
- X }
- X else
- X {
- X switch (dump)
- X {
- X case DUMP_HARDCOPY:
- X for (i = 0; i < screenheight; ++i)
- X {
- X p = fore->image[i];
- X for (k = screenwidth - 1; k >= 0 && p[k] == ' '; --k)
- X ;
- X for (j = 0; j <= k; ++j)
- X putc(p[j], f);
- X putc('\n', f);
- X }
- X break;
- X case DUMP_TERMCAP:
- X if ((p = index(MakeTermcap(fore->aflag), '=')) != NULL)
- X {
- X fputs(++p, f);
- X putc('\n', f);
- X }
- X break;
- X#ifdef COPY_PASTE
- X case DUMP_EXCHANGE:
- X p = copybuffer;
- X for (i = 0; i < copylen; i++)
- X putc(*p++, f);
- X break;
- X#endif
- X }
- X (void) fclose(f);
- X UserReturn(1);
- X }
- X }
- X if (UserStatus() <= 0)
- X Msg(0, "Cannot open \"%s\"", fn);
- X else
- X {
- X switch (dump)
- X {
- X case DUMP_TERMCAP:
- X Msg(0, "Termcap entry written to \"%s\".", fn);
- X break;
- X case DUMP_HARDCOPY:
- X Msg(0, "Screen image written to \"%s\".", fn);
- X break;
- X#ifdef COPY_PASTE
- X case DUMP_EXCHANGE:
- X Msg(0, "Copybuffer written to \"%s\".", fn);
- X#endif
- X }
- X }
- X}
- X
- X#ifdef COPY_PASTE
- X
- void
- ReadFile()
- X{
- X int i, l, size;
- X char fn[1024], c;
- X struct stat stb;
- X
- X sprintf(fn, "/tmp/%s", BUFFERFILE);
- X debug1("ReadFile(%s)\n", fn);
- X if ((i = secopen(fn, O_RDONLY, 0)) < 0)
- X {
- X Msg(errno, "no %s -- no slurp", fn);
- X return;
- X }
- X if (fstat(i, &stb))
- X {
- X Msg(errno, "no good %s -- no slurp", fn);
- X close(i);
- X return;
- X }
- X size = stb.st_size;
- X if (copybuffer)
- X Free(copybuffer);
- X copylen = 0;
- X if ((copybuffer = malloc(size)) == NULL)
- X {
- X close(i);
- X Msg_nomem;
- X return;
- X }
- X errno = 0;
- X if ((l = read(i, copybuffer, size)) != size)
- X {
- X copylen = (l > 0) ? l : 0;
- X#ifdef NETHACK
- X if (nethackflag)
- X Msg(errno, "You choke on your food: %d bytes", copylen);
- X else
- X#endif
- X Msg(errno, "Got only %d bytes from %s", copylen, fn);
- X close(i);
- X return;
- X }
- X copylen = l;
- X if (read(i, &c, 1) > 0)
- X Msg(0, "Slurped only %d characters into buffer - try again", copylen);
- X else
- X Msg(0, "Slurped %d characters into buffer", copylen);
- X close(i);
- X return;
- X}
- X
- void
- KillBuffers()
- X{
- X char fn[1024];
- X sprintf(fn, "/tmp/%s", BUFFERFILE);
- X errno = 0;
- X if (access(fn, W_OK) == -1)
- X {
- X Msg(errno, "%s not removed", fn);
- X return;
- X }
- X else
- X {
- X unlink(fn);
- X Msg(errno, "%s removed", fn);
- X }
- X}
- X#endif /* COPY_PASTE */
- X
- X#ifdef USRLIMIT
- CountUsers()
- X{
- X#ifdef GETUTENT
- X struct utmp *ut, *getutent();
- X#else
- X struct utmp utmpbuf;
- X#endif
- X int UserCount;
- X
- X debug1("CountUsers() - utmp=%d\n",utmp);
- X if (!utmp)
- X return(0);
- X UserCount = 0;
- X#ifdef GETUTENT
- X setutent();
- X while (ut = getutent())
- X if (ut->ut_type == USER_PROCESS)
- X UserCount++;
- X#else
- X (void) lseek(utmpf, (off_t) 0, 0);
- X while (read(utmpf, &utmpbuf, sizeof(struct utmp)) > 0)
- X {
- X if (utmpbuf.ut_name[0] != '\0')
- X UserCount++;
- X }
- X#endif
- X return(UserCount);
- X}
- X#endif
- X
- X#ifdef UTMPOK
- X
- static slot_t loginslot;
- static struct utmp utmp_logintty;
- X#ifdef _SEQUENT_
- static char loginhost[100+1];
- X#endif
- X
- void
- InitUtmp()
- X{
- X debug("InitUtmp testing...\n");
- X if ((utmpf = open(UtmpName, O_RDWR)) == -1)
- X {
- X if (errno != EACCES)
- X Msg(errno, UtmpName);
- X debug("InitUtmp failed.\n");
- X utmp = 0;
- X return;
- X }
- X#ifdef GETUTENT
- X close(utmpf);
- X utmpf= -1;
- X#endif
- X#ifdef MIPS
- X if ((utmpfappend = open(UtmpName, O_APPEND)) == -1)
- X {
- X if (errno != EACCES)
- X Msg(errno, UtmpName);
- X return;
- X }
- X#endif
- X utmp = 1;
- X ReInitUtmp();
- X}
- X
- void
- ReInitUtmp()
- X{
- X if (!utmp)
- X {
- X debug("Reinitutmp: utmp == 0\n");
- X return;
- X }
- X debug("(Re)InitUtmp: removing your logintty\n");
- X loginslot = TtyNameSlot(ttyname(0));
- X if (loginslot!=(slot_t)0 && loginslot!=(slot_t)-1)
- X {
- X#ifdef _SEQUENT_
- X if (p=ut_find_host(loginslot))
- X strncpy(loginhost, p, 100);
- X#endif
- X RemoveLoginSlot(loginslot, &utmp_logintty);
- X }
- X debug1(" slot %d zapped\n", loginslot);
- X}
- X
- void
- RestoreLoginSlot()
- X{
- X debug("RestoreLoginSlot()\n");
- X if (utmp && loginslot!=(slot_t)0 && loginslot!=(slot_t)-1)
- X {
- X#ifdef GETUTENT
- X# ifdef _SEQUENT_
- X int fail;
- X debug1(" logging you in again (slot %s)\n", loginslot);
- X/*
- X * We have problems if we add the console and use ut_add_user()
- X * because the id will be 'scon' instead of 'co'. So we
- X * restore it with pututline(). The reason why we don't use
- X * pututline all the time is that we want to set the host field.
- X * Unfortunatelly this can only be done with ut_add_user().
- X */
- X if (*loginhost)
- X {
- X fail = (ut_add_user(LoginName, loginslot, utmp_logintty.ut_pid,
- X *loginhost?loginhost:(char *)0) == 0);
- X }
- X else
- X {
- X setutent();
- X fail = (pututline(&utmp_logintty) == 0);
- X }
- X if (fail)
- X# else /* _SEQUENT_ */
- X debug1(" logging you in again (slot %s)\n", loginslot);
- X setutent();
- X if (pututline(&utmp_logintty)==0)
- X# endif /* _SEQUENT */
- X#else /* GETUTENT */
- X debug1(" logging you in again (slot %d)\n", loginslot);
- X# ifdef sequent
- X /* call sequent undocumented routine to count logins and add utmp entry if possible */
- X if (add_utmp(loginslot, &utmp_logintty) == -1)
- X# else
- X (void) lseek(utmpf, (off_t) (loginslot * sizeof(struct utmp)), 0);
- X if (write(utmpf, (char *) &utmp_logintty, sizeof(struct utmp))
- X != sizeof(struct utmp))
- X# endif /* sequent */
- X#endif /* GETUTENT */
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X Msg(errno, "/etc/utmp is to hard to dig");
- X else
- X#endif
- X Msg(errno,"Could not write /etc/utmp");
- X }
- X }
- X loginslot = (slot_t) 0;
- X}
- X
- void
- RemoveLoginSlot(slot, up)
- slot_t slot;
- struct utmp *up;
- X{
- X#ifdef GETUTENT
- X struct utmp *uu;
- X#endif
- X struct utmp u;
- X
- X#ifdef GETUTENT
- X debug2("RemoveLoginSlot(%s, %08x)\n", (slot == (slot_t) 0 ||
- X slot == (slot_t) -1 ) ? "no slot" : slot, up);
- X#else
- X debug2("RemoveLoginSlot(%d, %08x)\n", slot, up);
- X#endif
- X if (!utmp)
- X return;
- X if (slot != (slot_t) 0 && slot != (slot_t) -1)
- X {
- X bzero((char *) &u, sizeof u);
- X#ifdef GETUTENT
- X setutent();
- X strncpy(u.ut_line, slot, sizeof(u.ut_line));
- X if ((uu = getutline(&u)) == 0)
- X {
- X DeadlyMsg = 0;
- X Msg(0, "Utmp slot not found -> not removed");
- X return;
- X }
- X *up= *uu;
- X# ifdef _SEQUENT_
- X if (ut_delete_user(slot, uu->ut_pid, 0, 0) == 0)
- X# else
- X uu->ut_type = DEAD_PROCESS;
- X uu->ut_exit.e_termination = 0;
- X uu->ut_exit.e_exit= 0;
- X if (pututline(uu) == 0)
- X# endif
- X#else
- X (void) lseek(utmpf, (off_t) (slot * sizeof u), 0);
- X if (read(utmpf, (char *) up, sizeof u) != sizeof u)
- X {
- X DeadlyMsg = 0;
- X Msg(errno, "cannot read /etc/utmp ???");
- X sleep(1);
- X }
- X (void) lseek(utmpf, (off_t) (slot * sizeof u), 0);
- X if (write(utmpf, (char *) &u, sizeof u) != sizeof u)
- X#endif
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X {
- X DeadlyMsg = 0;
- X Msg(errno, "/etc/utmp is to hard to dig");
- X }
- X else
- X#endif
- X {
- X DeadlyMsg = 0;
- X Msg(errno,"Could not write /etc/utmp");
- X }
- X }
- X }
- X else
- X {
- X debug1("There is no utmp-slot to be removed(%d)\n", slot);
- X }
- X}
- X
- static char *stripdev(nam)
- char *nam;
- X{
- X if (nam == 0)
- X return(0);
- X if (strncmp(nam, "/dev/", 5) == 0)
- X return(nam + 5);
- X return(nam);
- X}
- X
- static slot_t TtyNameSlot(nam)
- char *nam;
- X{
- X char *name;
- X register slot_t slot;
- X#ifndef GETUTENT
- X register struct ttyent *tp;
- X#endif
- X
- X debug1("TtyNameSlot(%s)\n", nam);
- X if (!utmp || nam == NULL)
- X return (slot_t)0;
- X name = stripdev(nam);
- X#ifdef GETUTENT
- X slot = name;
- X#else
- X slot = 1;
- X setttyent();
- X while ((tp = getttyent()) != NULL && strcmp(name, tp->ty_name) != 0)
- X {
- X debug2("'%s' %d, ", tp->ty_name, slot);
- X ++slot;
- X }
- X debug("\n");
- X# ifdef MIPS
- X if (tp == NULL)
- X {
- X slot = CreateUtmp(name);
- X }
- X# endif /* MIPS */
- X#endif
- X return slot;
- X}
- X
- int
- SetUtmp(wi, displaynumber)
- struct win *wi;
- int displaynumber;
- X{
- X register char *p;
- X register slot_t slot;
- X char *line;
- X struct utmp u;
- X#ifdef UTHOST
- X# ifdef _SEQUENT_
- X char host[100+5];
- X# else
- X char host[sizeof(utmp_logintty.ut_host)+5];
- X# endif
- X#endif
- X
- X wi->slot = (slot_t) 0;
- X if (!utmp)
- X return -1;
- X if ((slot = TtyNameSlot(wi->tty)) == (slot_t) NULL)
- X {
- X debug1("SetUtmp failed (tty %s).\n",wi->tty);
- X return -1;
- X }
- X debug2("SetUtmp %d will get slot %d...\n", displaynumber, (int)slot);
- X
- X#ifdef UTHOST
- X host[sizeof(host)-5] = '\0';
- X# ifdef _SEQUENT_
- X strncpy(host, loginhost, sizeof(host) - 5);
- X# else
- X strncpy(host, utmp_logintty.ut_host, sizeof(host) - 5);
- X# endif
- X if (loginslot != (slot_t)0 && loginslot != (slot_t)-1 && host[0] != '\0')
- X {
- X /*
- X * we want to set our ut_host field to something like
- X * ":ttyhf:s.0" or
- X * "faui45:s.0" or
- X * "132.199.81.4:s.0" but not
- X * "faui45.informati"......:s.0
- X */
- X for (p = host; *p; p++)
- X {
- X if ((*p < '0' || *p > '9') && (*p != '.'))
- X break;
- X }
- X if (*p)
- X {
- X for (p = host; *p; p++)
- X {
- X if (*p == '.')
- X {
- X *p = '\0';
- X break;
- X }
- X }
- X }
- X }
- X else
- X {
- X strncpy(host + 1, stripdev(ttyname(0)), sizeof(host) - 6);
- X host[0] = ':';
- X }
- X debug1("rlogin hostname: '%s'\n", host);
- X sprintf(host + strlen(host), ":S.%c", '0' + displaynumber);
- X debug1("rlogin hostname: '%s'\n", host);
- X#endif /* UTHOST */
- X
- X line = stripdev(wi->tty);
- X bzero((char *) &u, sizeof u);
- X#ifdef GETUTENT
- X# ifdef _SEQUENT_
- X if (ut_add_user(LoginName, slot, wi->wpid, host)==0)
- X# else
- X strncpy(u.ut_user, LoginName, sizeof(u.ut_user));
- X strncpy(u.ut_id, line + strlen(line) - 2, sizeof(u.ut_id));
- X strncpy(u.ut_line, line, sizeof(u.ut_line));
- X u.ut_pid = wi->wpid;
- X u.ut_type = USER_PROCESS;
- X (void) time(&u.ut_time);
- X# ifdef UTHOST
- X strncpy(u.ut_host, host, sizeof(u.ut_host));
- X# endif /* UTHOST */
- X if (pututline(&u) == 0)
- X# endif /* _SEQUENT_ */
- X#else /* GETUTENT */
- X strncpy(u.ut_line, line, sizeof(u.ut_line));
- X strncpy(u.ut_name, LoginName, sizeof(u.ut_name));
- X# ifdef UTHOST
- X strncpy(u.ut_host, host, sizeof(u.ut_host));
- X# endif /* UTHOST */
- X# ifdef MIPS
- X u.ut_type = 7; /* USER_PROCESS */
- X strncpy(u.ut_id, line + 3, 4);
- X# endif /* MIPS */
- X (void) time(&u.ut_time);
- X# ifdef sequent
- X/* call sequent undocumented routine to count logins and add utmp entry if possible */
- X if (add_utmp(slot, &u) == -1)
- X# else
- X (void) lseek(utmpf, (off_t) (slot * sizeof u), 0);
- X if (write(utmpf, (char *) &u, sizeof u) != sizeof u)
- X# endif /* sequent */
- X#endif /* GETUTENT */
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X Msg(errno, "/etc/utmp is to hard to dig");
- X else
- X#endif
- X Msg(errno,"Could not write /etc/utmp");
- X return -1;
- X }
- X debug("SetUtmp successful\n");
- X wi->slot = slot;
- X return 0;
- X}
- X
- X#ifdef MIPS
- X
- X#define GETTTYENT
- static int ttyfd = 0;
- X
- static void setttyent()
- X{
- X if (ttyfd)
- X close(ttyfd);
- X ttyfd = open(UtmpName, O_RDONLY);
- X}
- X
- static struct ttyent *getttyent()
- X{
- X static struct utmp u;
- X static struct ttyent t;
- X
- X if (!ttyfd)
- X return NULL;
- X
- X if (read(ttyfd, &u, sizeof u))
- X {
- X t.ty_name = u.ut_line;
- X return &t;
- X }
- X return NULL;
- X}
- X
- CreateUtmp(name)
- char *name;
- X{
- X int slot;
- X struct utmp u;
- X
- X strncpy(u.ut_line, name, 8);
- X strncpy(u.ut_name, LoginName, 8);
- X u.ut_type = 7; /* USER_PROCESS */
- X strncpy(u.ut_id, name+3, 4);
- X (void) time(&u.ut_time);
- X slot = (lseek(utmpfappend, 0, 2) + 1) / sizeof u;
- X (void) write(utmpfappend, (char *)&u, sizeof u);
- X close(utmpfappend);
- X if ((utmpfappend = open(UtmpName, O_APPEND)) == -1)
- X {
- X if (errno != EACCES)
- X Msg(errno, UtmpName);
- X return;
- X }
- X return slot;
- X}
- X#endif /* MIPS */
- X
- X/*
- X * if slot could be removed or was 0, wi->slot = -1;
- X * else not changed.
- X */
- int
- RemoveUtmp(wi)
- struct win *wi;
- X{
- X#ifdef GETUTENT
- X struct utmp *uu;
- X#endif
- X struct utmp u;
- X slot_t slot;
- X
- X slot=wi->slot;
- X#ifdef GETUTENT
- X debug1("RemoveUtmp(%s)\n", (slot == (slot_t) 0) ?
- X "no slot (0)":((slot == (slot_t) -1) ? "no slot (-1)" : slot));
- X#else
- X debug1("RemoveUtmp(wi.slot: %d)\n", slot);
- X#endif
- X if (!utmp)
- X return -1;
- X if (slot == (slot_t) 0 || slot == (slot_t) -1)
- X {
- X debug1("There is no utmp-slot to be removed(%d)\n", slot);
- X wi->slot = (slot_t) -1;
- X return 0;
- X }
- X bzero((char *) &u, sizeof u);
- X#ifdef GETUTENT
- X setutent();
- X strncpy(u.ut_line, slot, sizeof(u.ut_line));
- X if ((uu = getutline(&u)) == 0)
- X {
- X Msg(0, "Utmp slot not found -> not removed");
- X return -1;
- X }
- X# ifdef _SEQUENT_
- X if (ut_delete_user(slot, uu->ut_pid, 0, 0) == 0)
- X# else
- X uu->ut_type = DEAD_PROCESS;
- X uu->ut_exit.e_termination = 0;
- X uu->ut_exit.e_exit= 0;
- X if (pututline(uu) == 0)
- X# endif
- X#else /* GETUTENT */
- X (void) lseek(utmpf, (off_t) (slot * sizeof u), 0);
- X if (write(utmpf, (char *) &u, sizeof u) != sizeof u)
- X#endif
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X Msg(errno, "/etc/utmp is to hard to dig");
- X else
- X#endif
- X Msg(errno,"Could not write /etc/utmp");
- X return -1;
- X }
- X debug("RemoveUtmp successful\n");
- X wi->slot = (slot_t) -1;
- X return 0;
- X}
- X
- X#endif /* UTMPOK */
- X
- X#if !defined(GETTTYENT) && !defined(GETUTENT)
- X
- static void setttyent()
- X{
- X struct stat s;
- X register int f;
- X register char *p, *ep;
- X
- X if (ttnext)
- X {
- X ttnext = tt;
- X return;
- X }
- X if ((f = open(ttys, O_RDONLY)) == -1 || fstat(f, &s) == -1)
- X Msg(errno, ttys);
- X if ((tt = malloc((unsigned) s.st_size + 1)) == 0)
- X Msg_nomem;
- X if (read(f, tt, s.st_size) != s.st_size)
- X Msg(errno, ttys);
- X close(f);
- X for (p = tt, ep = p + s.st_size; p < ep; ++p)
- X if (*p == '\n')
- X *p = '\0';
- X *p = '\0';
- X ttnext = tt;
- X}
- X
- static struct ttyent *getttyent()
- X{
- X static struct ttyent t;
- X
- X if (*ttnext == '\0')
- X return NULL;
- X t.ty_name = ttnext + 2;
- X ttnext += strlen(ttnext) + 1;
- X return &t;
- X}
- X
- X#endif /* GETTTYENT */
- X
- X#ifdef LOADAV
- X
- void
- InitKmem()
- X{
- X debug("Init Kmem...\n");
- X if ((kmemf = open(KmemName, O_RDONLY)) == -1)
- X return;
- X debug("Kmem opened\n");
- X nl[0].n_name = AvenrunSym;
- X debug2("Searching in %s for %s\n", UnixName, nl[0].n_name);
- X nlist(UnixName, nl);
- X if (/* nl[0].n_type == 0 || */ nl[0].n_value == 0)
- X {
- X close(kmemf);
- X return;
- X }
- X debug("AvenrunSym found!!\n");
- X avenrun = 1;
- X}
- X
- int
- GetAvenrun()
- X{
- X if (lseek(kmemf, (off_t) nl[0].n_value, 0) == (off_t) - 1)
- X return 0;
- X if (read(kmemf, (char *) loadav, sizeof loadav) != sizeof loadav)
- X return 0;
- X
- X return 1;
- X}
- X
- X#endif /* LOADAV */
- X
- X
- X/*
- X * (Almost) secure open and fopen... mlschroe.
- X */
- X
- XFILE *
- secfopen(name, mode)
- char *name;
- char *mode;
- X{
- X FILE *fi;
- X#ifdef NOREUID
- X int flags, fd;
- X#endif
- X
- X debug2("secfopen(%s, %s)\n", name, mode);
- X if (eff_uid == real_uid)
- X return(fopen(name, mode));
- X#ifndef NOREUID
- X setreuid(eff_uid, real_uid);
- X setregid(eff_gid, real_gid);
- X fi = fopen(name, mode);
- X setreuid(real_uid, eff_uid);
- X setregid(real_gid, eff_gid);
- X#else
- X if (mode[0] && mode[1] == '+')
- X flags = O_RDWR;
- X else
- X flags = (mode[0] == 'r') ? O_RDONLY : O_WRONLY;
- X if (mode[0] == 'w')
- X flags |= O_CREAT | O_TRUNC;
- X else if (mode[0] == 'a')
- X flags |= O_CREAT | O_APPEND;
- X else if (mode[0] != 'r')
- X {
- X errno = EINVAL;
- X return(0);
- X }
- X if ((fd = secopen(name, flags, 0666)) < 0)
- X return(0);
- X if ((fi = fdopen(fd, mode)) == 0)
- X {
- X close(fd);
- X return(0);
- X }
- X#endif
- X return(fi);
- X}
- X
- X
- int
- secopen(name, flags, mode)
- char *name;
- int flags;
- int mode;
- X{
- X int fd;
- X#ifdef NOREUID
- X int q;
- X struct stat stb;
- X#endif
- X
- X debug3("secopen(%s, 0x%x, 0%03o)\n", name, flags, mode);
- X if (eff_uid == real_uid)
- X return(open(name, flags, mode));
- X#ifndef NOREUID
- X setreuid(eff_uid, real_uid);
- X setregid(eff_gid, real_gid);
- X fd = open(name, flags, mode);
- X setreuid(real_uid, eff_uid);
- X setregid(real_gid, eff_gid);
- X#else
- X /* Truncation/creation is done in UserContext */
- X if ((flags & O_TRUNC) || ((flags & O_CREAT) && access(name, F_OK)))
- X {
- X if (UserContext() > 0)
- X {
- X if ((fd = open(name, flags, mode)) >= 0)
- X {
- X close(fd);
- X UserReturn(0);
- X }
- X if (errno == 0)
- X errno = EACCES;
- X UserReturn(errno);
- X }
- X if (q = UserStatus())
- X {
- X if (q > 0)
- X errno = q;
- X return(-1);
- X }
- X }
- X if (access(name, F_OK))
- X return(-1);
- X if ((fd = open(name, flags & ~(O_TRUNC | O_CREAT), 0)) < 0)
- X return(-1);
- X debug("open successful\n");
- X if (fstat(fd, &stb))
- X {
- X close(fd);
- X return(-1);
- X }
- X debug("fstat successful\n");
- X if (stb.st_uid != real_uid)
- X {
- X switch (flags & (O_RDONLY | O_WRONLY | O_RDWR))
- X {
- X case O_RDONLY:
- X q = 0004;
- X break;
- X case O_WRONLY:
- X q = 0002;
- X break;
- X default:
- X q = 0006;
- X break;
- X }
- X if ((stb.st_mode & q) != q)
- X {
- X debug("secopen: permission denied\n");
- X close(fd);
- X errno = EACCES;
- X return(-1);
- X }
- X }
- X#endif
- X debug1("secopen ok - returning %d\n", fd);
- X return(fd);
- X}
- END_OF_FILE
- if test 49381 -ne `wc -c <'fileio.c'`; then
- echo shar: \"'fileio.c'\" unpacked with wrong size!
- fi
- # end of 'fileio.c'
- fi
- echo shar: End of archive 5 \(of 8\).
- cp /dev/null ark5isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 8 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-